{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Basic spectroscopy measurements"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This notebook is indended as a **starting point into spectroscopic (frequency domain) measurements with `qkit`**. We focus on measurements with vector network analyzers (VNAs) in the GHz regime.\n",
    "The notebook briefly covers the **`qkit` startup**, **initialization of measurement devices** and the use of a **`sample` object**. For a detailed view on these topic you will find **more information in their respective example notebooks**. \n",
    "After creating of an object of the `spectrum` class and parsing the device information to the object we can start measuring. The **`spectrum` class** offers frequency domain VNA measurements with up to two additional external sweep parameters. The data is stored in a hdf5 file and can be view and further analyzed."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# start qkit and import the needed modules. we here assume an already configured qkit measurement environment\n",
    "import qkit\n",
    "qkit.start()\n",
    "\n",
    "from qkit.measure.spectroscopy import spectroscopy\n",
    "import qkit.measure.samples_class as sc\n",
    "\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# initialize instruments; as an example we here work with a Keysight VNA, a Yokogawa current source, \n",
    "# and an Anritsu MW source\n",
    "vna = qkit.instruments.create('vna', 'Keysight_VNA_E5071C', address='TCPIP::XXX.XXX.XXX.XXX')\n",
    "yoko = qkit.instruments.create('yoko', 'Yokogawa_GS820', address='TCPIP::XXX.XXX.XXX.XXX')\n",
    "mw_src = qkit.instruments.create('mw_src', 'Anritsu_MG37022', address='TCPIP::XXX.XXX.XXX.XXX')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# create/load sample object; (optional), for more information see the example notebook on the sample class.\n",
    "sample_filepath = r'\\some\\path\\sample_1.sample'\n",
    "smpl = sc.Sample(sample_filepath)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Creating a `spectrum` object.** The `init` takes<br>\n",
    "* `vna`: `instrument` object (mandatory)<br>\n",
    "* `exp_name`: `string` (optional) for a brief name of the experiment<br>\n",
    "* `sample`: `sample` object (optional)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "s = spectroscopy.spectrum(vna=vna, sample = smpl)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The general **VNA parameters** (probing frequencies, power, etc.) can be either **set at the device or use the qkit instrument** command. Using sample object attributes is possible as well."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "vna.set_centerfreq(smpl.fr)\n",
    "vna.set_span(200e6)\n",
    "vna.set_averages(10)\n",
    "vna.set_Average(True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next we want to **record the VNA trace**. In the spectrum object the parameter `comment` can be used for all non-digital information. Any digitally available instrument settings are saved automatically."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "comment = \"\"\"\n",
    "    * -30dB attenuator @ VNA\n",
    "    \"\"\"\n",
    "\n",
    "s.comment = comment\n",
    "s.measure_1D()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For resonator measurements it is also possible to **fit the probed resonance live while measureing**. For the fits to converge the VNA parameters need to adjusted properly."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "comment = \"\"\"\n",
    "    * measure resonance in reflection\n",
    "    * -30dB attenuator @ VNA\n",
    "    \"\"\"\n",
    "s.set_resonator_fit(fit_function='circle_fit_reflection')\n",
    "s.comment = comment\n",
    "s.measure_1D()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A **sweep parameter** can be added to the `spectum` object and attributed to a sweep axis. In the example below we **measure a resonator agains a applied current (ie for creating a magnetic field bias)**. The current is swept from 0 to 1A in 1mA steps. After the measurement the current is ramped down again. **For one value of the x-parameter all VNA frequencies are probed before the next value of x is set.**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "comment = \"\"\"\n",
    "    * resonator vs applied current\n",
    "    * -30dB step attenuator @ VNA\n",
    "    \"\"\"\n",
    "s.comment = comment\n",
    "s.set_resonator_fit(fit_resonator=False)\n",
    "\n",
    "# x_func gets called for every value of i. Here it would be not necessary to define a function for only the ramp fct,\n",
    "# it will be useful in the next example.\n",
    "def x_func(i):\n",
    "    return yoko.ramp_current(i, 1e-3)\n",
    "\n",
    "s.set_x_parameters(x_vec = np.arange(0, 1, 1e-3),\n",
    "                  x_coordname = 'current',\n",
    "                  x_set_obj = x_func,\n",
    "                  x_unit = 'A')\n",
    "\n",
    "s.measure_2D()\n",
    "yoko.ramp_current(0, 1e-3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the next example the **VNA power is changed in addition to the current**. Depending on the applied power, the number of averages is changed."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# the x/y-loops are interleaved, y changes \"faster\" than x: \n",
    "#     1) each VNA freq at y0 and x0\n",
    "#     2) each VNA freq at y1 and x0\n",
    "#     ...\n",
    "#     3) each VNA freq at yN and x0\n",
    "#     4) each VNA freq at y0 and x1\n",
    "#     ...\n",
    "#     5) each VNA freq at yN and xM\n",
    "\n",
    "comment = \"\"\"\n",
    "    * resonator vs applied current at different power levels\n",
    "    * -30dB step attenuator @ VNA\n",
    "    \"\"\"\n",
    "s.comment = comment\n",
    "s.set_resonator_fit(fit_resonator=False)\n",
    "\n",
    "def x_func(i):\n",
    "    return yoko.ramp_current(i, 1e-3)\n",
    "\n",
    "# Here the called function features more commends, i.e. change the number of averages at different powers to shorten the\n",
    "# measurement time.\n",
    "def y_func(i):\n",
    "    if i < -25: vna.set_averages(10)\n",
    "    else: vna.set_averages(5)\n",
    "    return vna.set_power(i)\n",
    "\n",
    "s.set_x_parameters(x_vec = np.arange(0, 1.001, 1e-3),\n",
    "                  x_coordname = 'current',\n",
    "                  x_set_obj = x_func,\n",
    "                  x_unit = 'A')\n",
    "\n",
    "s.set_y_parameters(y_vec = np.arange(-35, 11, 5),\n",
    "                  y_coordname = 'power',\n",
    "                  y_set_obj = y_func,\n",
    "                  y_unit = 'dBm')\n",
    "\n",
    "s.measure_3D()\n",
    "yoko.ramp_current(0, 1e-3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The **`measure_iD()` command executes the measurement**. By default, the created **data file is opened in qviewkit**. After the measurement the **created datasets are plotted with default matplotlib settings**. A **progress bar** programmed in JavaScript shows the status during the measuremend and gives **additional information i.e. a estimated end time** for the measurement."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.15"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
